# """ 存放公共方法
# @Project: Rebar
# @File: public_func.py
# @Author: hzc
# @Date: 2023/3/23 13:32
# """
import decimal
from collections import defaultdict
from datetime import datetime, date
from enum import Enum

import numpy as np
import torch
from fastapi import status
from fastapi.responses import JSONResponse, Response

# from model.db import TbOrderDetails
from sqlalchemy.engine import RowProxy
from sqlalchemy.ext.declarative import declarative_base


Base = declarative_base()


def obj_to_dict(obj):
    """
    将对象转化为字典，将DateTime类型转换为字符串类型
    :param is_result:
    :param obj:
    :return:
    """
    if obj is None:
        return None
    result = {}
    try:

        """获得所有的键"""
        keys = obj.keys()
    except:
        try:
            keys = obj.__mapper__.c.keys()
        except:
            keys = obj.__dict__.keys()
    for key in keys:
        if key in ["user_pwd"]:  # 剔除不需要显示的字段
            continue
        try:
            value = getattr(obj, key)
        except:
            value = obj.get(key)
        if isinstance(value, datetime):  # 将DateTime类型转换为字符串类型
            value = value.strftime('%Y-%m-%d %H:%M:%S')
        if isinstance(value, date):
            value = value.strftime('%Y-%m-%d')
        if isinstance(value, decimal.Decimal):
            value = float(value)
        if isinstance(value, Enum):  # 输出枚举类型数据的value
            value = value.value
        result[key] = value
    return result


def objs_to_dict(objs):
    """
    将对象集合转化为列表
    :param is_result:
    :param objs:
    :return:
    """
    result = []
    if objs is None:
        return None
    for obj in objs:
        result.append(obj_to_dict(obj))
    return result


def need_serialize(data):
    if data is None or isinstance(data, str) or isinstance(data, int):
        return data
    else:
        if isinstance(data, list):
            return objs_to_dict(data)
        else:
            if isinstance(data, dict):
                for key in data.keys():
                    value = data.get(key)
                    data.update({
                        key: need_serialize(value)
                    })
                return data
            else:
                if isinstance(data, Base) or hasattr(data, "_asdict") or isinstance(data, RowProxy):
                    return obj_to_dict(data)
                else:
                    if isinstance(data, decimal.Decimal):
                        return float(data)
                    return str(data)


def compute_evaluation_index(objs):
    # 创建一个字典来保存参数的值
    param_values = defaultdict(list)
    # 遍历结果并整理数据
    for row in objs:
        core_name = row['Core_Name']
        parameter_name = row['Parameter_Name']
        parameter_value = row['Parameter_Value']
        if parameter_value is not None:
            param_values[parameter_name].append(float(parameter_value))

    # 计算每个参数的最大值、最小值和平均值
    param_stats = []
    for parameter_name, values in param_values.items():
        max_value = max(values)
        min_value = min(values)
        avg_value = sum(values) / len(values)
        values_array = np.array(values)
        variance = np.var(values_array)
        p10 = np.percentile(values_array, 10)
        p90 = np.percentile(values_array, 90)
        item = {
            "Parameter_Name": parameter_name,
            "Max_Value": max_value,
            "Min_Value": min_value,
            "Average_Value": '{:.2f}'.format(avg_value),
            "Variance": '{:.2f}'.format(variance),
            "P10": '{:.2f}'.format(p10),
            "P90": '{:.2f}'.format(p90)
        }
        param_stats.append(item)
    return param_stats


# 合并同一Core_ID
def transform_Datasets(data):
    modified_data = []
    for item in data:
        core_id = item["Core_ID"]
        core_name = item["Core_Name"]
        parameter_ecode = item["Parameter_Ecode"]
        parameter_value = item["Parameter_Value"]

        if core_id not in [x["Core_ID"] for x in modified_data]:
            modified_data.append({"Core_ID": core_id, "Core_Name": core_name})

        core_data = next((x for x in modified_data if x["Core_ID"] == core_id), None)
        core_data[parameter_ecode] = parameter_value
    return modified_data


def datasets_to_tensor(X, Y):
    X_data = transform_Datasets(X)
    Y_data = transform_Datasets(Y)
    # 去除"Core_ID"和"Core_Name"这两个固定属性
    X_train_data = [{k: v for k, v in data_dict.items() if k not in ['Core_ID', 'Core_Name']} for data_dict in X_data]
    # 构建通用的X_train张量
    X_train = torch.tensor([list(data_dict.values()) for data_dict in X_train_data])
    # 去除"Core_ID"和"Core_Name"这两个固定属性
    Y_train_data = [{k: v for k, v in data_dict.items() if k not in ['Core_ID', 'Core_Name']} for data_dict in Y_data]

    # 构建通用的Y_train张量
    Y_train = torch.tensor([list(data_dict.values()) for data_dict in Y_train_data])
    return X_train, Y_train


# def datasets_to_ndarray(X, Y,model_id):
#     X_data = transform_Datasets(X)
#     Y_data = transform_Datasets(Y)
#     # 去除"Core_ID"和"Core_Name"这两个固定属性
#     X_train_data = [{k: v for k, v in data_dict.items() if k not in ['Core_ID', 'Core_Name']} for data_dict in X_data]
#     # 构建通用的X_train张量
#     # X_train = np.array([list(data_dict.values()) for data_dict in X_train_data])
#     # 获取属性顺序
#     inputParams, outputParams = get_model_paras(model_id)
#     keys =[item['Parameter_Ecode'] for item in  inputParams]
#     # 确定数值属性的索引
#     value_indices = [keys.index(key) for key in keys if key not in ['Core_ID', 'Core_Name']]
#     # 提取数值部分
#     values = [[item[key] for key in keys if key not in ['Core_ID', 'Core_Name']] for item in X_train_data]
#
#     # 转换为ndarray
#     result_array = np.array(values)[:, value_indices]
#     # 去除"Core_ID"和"Core_Name"这两个固定属性
#     Y_train_data = [{k: v for k, v in data_dict.items() if k not in ['Core_ID', 'Core_Name']} for data_dict in Y_data]
#
#
#     # 构建通用的Y_train张量
#     Y_train = np.array([list(data_dict.values()) for data_dict in Y_train_data]).transpose()[0, :]
#     return result_array, Y_train


def datasets_to_tensor_split(X, Y, paras):
    X_data = transform_Datasets(X)
    Y_data = transform_Datasets(Y)
    # 筛选属性
    X_train_data = [{k: v for k, v in data_dict.items() if k in paras} for data_dict in X_data]
    # 构建通用的X_train张量
    X_train = torch.tensor([list(data_dict.values()) for data_dict in X_train_data])
    # 筛选属性
    Y_train_data = [{k: v for k, v in data_dict.items() if k in paras} for data_dict in Y_data]

    # 构建通用的Y_train张量
    Y_train = torch.tensor([list(data_dict.values()) for data_dict in Y_train_data])
    return X_train, Y_train


def discard_Core(X_data):
    # 去除"Core_ID"和"Core_Name"这两个固定属性
    # 收集所有可能出现的属性
    all_attributes = set()
    for data in X_data:
        all_attributes.update(data.keys())
    all_attributes.discard("Core_ID")
    all_attributes.discard("Core_Name")
    X_train_data = [[data[attr] if attr in data else 0 for attr in all_attributes] for data in X_data]
    return X_train_data


def modified_data(data):
    modified_data = []
    for item in data:
        core_id = item["Core_ID"]
        core_name = item["Core_Name"]
        parameter_ecode = item["Parameter_Ecode"]
        parameter_value = item["Parameter_Value"]

        if core_id not in [x["Core_ID"] for x in modified_data]:
            modified_data.append({"Core_ID": core_id, "Core_Name": core_name})

        core_data = next((x for x in modified_data if x["Core_ID"] == core_id), None)
        core_data[parameter_ecode] = parameter_value
    return modified_data


def call_function(function_name, parameter):
    func = globals()[function_name]  # 获取函数对象
    result = func(parameter)  # 调用函数
    return result
